package com.snail.billing.page.view;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;

import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.ProgressBar;

import com.android.util.ResUtil;
import com.snail.billing.Billing;
import com.snail.billing.DataCache;
import com.snail.billing.Resource;
import com.snail.billing.data.Account;
import com.snail.billing.data.AccountManager;
import com.snail.billing.page.UserCenterPage;
import com.snail.billing.page.WebViewPage;
import com.snail.billing.sso.DefaultTicketRetriever;
import com.snail.billing.sso.HttpConnection;

public class FloatView extends ImageView implements OnClickListener, HideEvent {
	private float[] temp = new float[4];
	private WindowManager.LayoutParams wLayoutParams;
	private WindowManager mWindowManager;
	private boolean viewAdded = false;
	private int statusBarHeight = 0;
	private int lastAction;
	private int minMove = 10;
	private int screenWidth, screenHeight;
	private final int viewDpWidth = 50;
	private final String FLOAT_X = "float_x";
	private final String FLOAT_Y = "float_Y";
	private int viewWidth;
	public static boolean isShow = true;
	private static ArrayList<WeakReference<HideEvent>> mEventHideList = new ArrayList<WeakReference<HideEvent>>();

	private Handler handler;
	private Runnable runnable = new Runnable() {

		@Override
		public void run() {
			FloatView.super.setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_image));
		}
	};

	public FloatView(Context context) {
		super(context);
		mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		wLayoutParams = new LayoutParams();
		wLayoutParams.width = getViewWidth();
		wLayoutParams.height = getViewWidth();
		wLayoutParams.format = PixelFormat.TRANSLUCENT;
		wLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
		wLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
		wLayoutParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_FULLSCREEN | LayoutParams.FLAG_LAYOUT_INSET_DECOR;
		setId(FloatId.FLOAT_IMAGE);
		setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_image2));
		init();
		handler = new Handler(Looper.getMainLooper());
		handler.postDelayed(runnable, 5000);
	}

	private int getViewWidth() {
		if (viewWidth == 0) {
			viewWidth = dpToPx(viewDpWidth, getContext());
		}
		return viewWidth;
	}

	private void init() {
		screenWidth = getResources().getDisplayMetrics().widthPixels;
		screenHeight = getResources().getDisplayMetrics().heightPixels;
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
		int x = sp.getInt(FLOAT_X, 0);
		int y = sp.getInt(FLOAT_Y, 0);
		if (x > 0 && x != screenWidth - getViewWidth()) {
			x = screenWidth - getViewWidth();
		}
		if (y > screenHeight) {
			y = screenHeight - getViewWidth();
		}

		wLayoutParams.x = x;
		wLayoutParams.y = y;
		refresh();
	}

	@Override
	protected void onConfigurationChanged(Configuration newConfig) {
		boolean isLeft = true;
		if (wLayoutParams.x > screenWidth / 2) {
			isLeft = false;
		}
		screenWidth = getResources().getDisplayMetrics().widthPixels;
		screenHeight = getResources().getDisplayMetrics().heightPixels;
		if (isLeft) {
			wLayoutParams.x = 0;
		} else {
			wLayoutParams.x = screenWidth - getWidth();
		}
		refresh();
		super.onConfigurationChanged(newConfig);
	}

	public void destory() {
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
		sp.edit().putInt(FLOAT_X, wLayoutParams.x).putInt(FLOAT_Y, wLayoutParams.y).commit();
		try {
			removeHideEvent();
			mWindowManager.removeViewImmediate(this);
			System.gc();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void removeHideEvent() {
		Iterator<WeakReference<HideEvent>> itr = mEventHideList.iterator();
		while (itr.hasNext()) {
			WeakReference<HideEvent> tmp = itr.next();
			if (tmp.get() == this)
				itr.remove();
		}
	}

	private void hideAllView() {
		Iterator<WeakReference<HideEvent>> itr = mEventHideList.iterator();
		while (itr.hasNext()) {
			WeakReference<HideEvent> tmp = itr.next();
			HideEvent hideEvent = tmp.get();
			if (hideEvent != null) {
				hideEvent.onHide();
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (getVisibility() != View.VISIBLE)
			return super.onTouchEvent(event);
		if (isAnim)
			return true;
		handler.removeCallbacks(runnable);
		switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				temp[0] = event.getX();
				temp[1] = event.getY();
				temp[2] = event.getX() - getLeft();
				temp[3] = event.getY() - getTop();
				lastAction = MotionEvent.ACTION_DOWN;
			break;
			case MotionEvent.ACTION_MOVE:
				if (lastAction == MotionEvent.ACTION_DOWN) {
					if (Math.abs(event.getX() - temp[0]) > minMove || Math.abs(event.getY() - temp[1]) > minMove) {
						lastAction = MotionEvent.ACTION_MOVE;
						if (isPopwinShow()) {
							mPopWin.dismiss();
						}
						refreshView((int) event.getRawX(), (int) event.getRawY());
					}
				} else {
					refreshView((int) event.getRawX(), (int) event.getRawY());
				}
			break;
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_CANCEL:
				if (lastAction == MotionEvent.ACTION_DOWN) {
					onClick(this);
				} else if (wLayoutParams.x != 0 && wLayoutParams.x != screenWidth - getWidth()) {
					isAnim = true;
					postInvalidate();
				}
			break;

			default:
			break;
		}
		return super.onTouchEvent(event);
	}

	boolean isAnim = false;

	@Override
	protected void onDraw(Canvas canvas) {
		if (isAnim) {
			if (wLayoutParams.x == 0 || wLayoutParams.x == screenWidth - getWidth()) {
				isAnim = false;
				SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
				sp.edit().putInt(FLOAT_X, wLayoutParams.x).putInt(FLOAT_Y, wLayoutParams.y).commit();
				handler.postDelayed(runnable, 5000);
			} else {
				if (wLayoutParams.x < screenWidth / 2) {
					wLayoutParams.x -= 30;
					if (wLayoutParams.x <= 0) {
						wLayoutParams.x = 0;
					}
					refresh();
				} else {
					wLayoutParams.x += 30;
					if (wLayoutParams.x > screenWidth - getWidth()) {
						wLayoutParams.x = screenWidth - getWidth();
					}
					refresh();
				}
				invalidate();
			}
		}
		super.onDraw(canvas);
	}

	/**
	 * 刷新悬浮窗
	 * 
	 * @param x
	 *            当前X轴绝对坐标
	 * @param y
	 *            当前的Y轴绝对坐标
	 */
	private void refreshView(int x, int y) {
		// 状态栏高度不能立即取，不然得到的值是0
		if (statusBarHeight == 0) {
			View rootView = this.getRootView();
			Rect r = new Rect();
			rootView.getWindowVisibleDisplayFrame(r);
			statusBarHeight = r.top;
		}

		wLayoutParams.x = x - (int) temp[2];
		// y轴减去状态栏的高度，因为状态栏不是用户可以绘制的区域，不然拖动的时候会有跳动
		if (y >= 0) {
			wLayoutParams.y = y - statusBarHeight - (int) temp[3];// STATUS_HEIGHT;
		}
		if (wLayoutParams.x < 0) {
			wLayoutParams.x = 0;
		}
		if (wLayoutParams.x > screenWidth - getWidth()) {
			wLayoutParams.x = screenWidth - getWidth();
		}
		if (wLayoutParams.y < 0) {
			wLayoutParams.y = 0;
		}
		if (wLayoutParams.y > screenHeight - getWidth() - statusBarHeight) {
			wLayoutParams.y = screenHeight - getWidth() - statusBarHeight;
		}
		refresh();
	}

	@Override
	public void setVisibility(int visibility) {
		if (visibility != VISIBLE && isPopwinShow()) {
			mPopWin.dismiss();
		}
		if (!isShow) {
			visibility = GONE;
		}
		super.setVisibility(visibility);
	}

	/**
	 * 添加悬浮窗或者更新悬浮窗 如果悬浮窗还没添加则添加 如果已经添加则更新其位置
	 */
	private void refresh() {
		try {
			if (viewAdded) {
				mWindowManager.updateViewLayout(this, wLayoutParams);
			} else {
				setVisibility(getVisibility());
				mWindowManager.addView(this, wLayoutParams);
				mEventHideList.add(new WeakReference<HideEvent>(this));
				viewAdded = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
			case FloatId.FLOAT_IMAGE:
				if (isPopwinShow()) {
					mPopWin.dismiss();
				} else {
					showPopWindow();
					handler.removeCallbacks(runnable);
				}
			break;
			case FloatId.FLOAT_ICON1:
				if (isPopwinShow()) {
					mPopWin.dismiss();
				}
				DataCache.getInstance().importParams.pageClass = UserCenterPage.class;
				getContext().startActivity(new Intent(getContext(), Billing.class));
			break;
			case FloatId.FLOAT_ICON2:
				if (isPopwinShow()) {
					mPopWin.dismiss();
				}
				SsoTask ssoTask = new SsoTask();
				ssoTask.execute(ResUtil.getString(Resource.string.snailbilling_float_text2), ResUtil.getString(Resource.string.snailbilling_config_bbs));
			break;
			case FloatId.FLOAT_ICON3:
				if (isPopwinShow()) {
					mPopWin.dismiss();
				}
				SsoTask ssoTask2 = new SsoTask();
				ssoTask2.execute(ResUtil.getString(Resource.string.snailbilling_float_text3), ResUtil.getString(Resource.string.snailbilling_config_official));
			break;
		}

	}

	private class SsoTask extends AsyncTask<String, Void, Void> {

		Dialog dialog;
		String ssoServer = "https://sso.woniu.com/v1/tickets";
		String title;
		String serviceUri;
		String tgt;
		String st;

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			dialog = new Dialog(getContext());
			dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
			dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
			ProgressBar bar = new ProgressBar(getContext());
			dialog.setContentView(bar);
			dialog.show();
		}

		@Override
		protected Void doInBackground(String... params) {
			title = params[0];
			serviceUri = params[1];
			Account account = AccountManager.getCurrentAccount();
			String username = account.getAccount();
			String password = account.getPwd();
			try {
				DefaultTicketRetriever ssoSdk = new DefaultTicketRetriever();
				ssoSdk.setConnection(HttpConnection.getInstance());
				tgt = ssoSdk.getTicketGrantingTicket(ssoServer, username, password);
				Log.d("sso", "TGT=" + tgt);
				st = ssoSdk.getServiceTicket(ssoServer, tgt, serviceUri);
				Log.d("sso", "ST=" + st);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			dialog.dismiss();
			String url = serviceUri + "&ticket=" + st;
			DataCache.getInstance().importParams.pageClass = WebViewPage.class;
			Intent intent = new Intent(getContext(), Billing.class);
			intent.putExtra(WebViewPage.TITLE, title);
			intent.putExtra(WebViewPage.URL, url);
			getContext().startActivity(intent);
		}

	}

	private boolean isPopwinShow() {
		return mPopWin != null && mPopWin.isShowing();
	}

	private int[] leftdrawRes = new int[] { ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon1),
			//
			ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon2),
			//
			ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon3) };
	private int[] rightdrawRes = new int[] { ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon1),
			//
			ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon2),
			//
			ResUtil.getDrawableId(Resource.drawable.snailbilling_float_icon3) };
	private int[] leftIds = new int[] { FloatId.FLOAT_ICON1, FloatId.FLOAT_ICON2, FloatId.FLOAT_ICON3 };
	private int[] rightIds = new int[] { FloatId.FLOAT_ICON1, FloatId.FLOAT_ICON2, FloatId.FLOAT_ICON3 };
	private PopupWindow mPopWin;
	private ImageView[] buttons;
	private LinearLayout popLayout;
	private ImageView imageLeft, imageRight;
	int popWidth;

	private void showPopWindow() {
		if (wLayoutParams.x != 0 && wLayoutParams.x != screenWidth - getWidth())
			return;
		int buttonNum = 3;
		if (mPopWin == null) {
			int topMargin = 12 * getViewWidth() / 144;
			int margin = dpToPx(5, getContext());
			//
			LinearLayout allLayout = new LinearLayout(getContext());
			allLayout.setOrientation(LinearLayout.HORIZONTAL);
			//
			imageLeft = new ImageView(getContext());
			imageLeft.setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_bg_l));
			imageLeft.setScaleType(ScaleType.FIT_XY);
			LinearLayout.LayoutParams imageLeftParams = new LinearLayout.LayoutParams(getViewWidth() * 68 / 144, getViewWidth() * 120 / 144);
			imageLeftParams.setMargins(0, topMargin, 0, topMargin);
			allLayout.addView(imageLeft, imageLeftParams);
			//
			popLayout = new LinearLayout(getContext());
			popLayout.setOrientation(LinearLayout.HORIZONTAL);
			popLayout.setBackgroundResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_bg));
			LinearLayout.LayoutParams popLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, getViewWidth() * 120 / 144);
			popLayoutParams.setMargins(0, topMargin, 0, topMargin);
			allLayout.addView(popLayout, popLayoutParams);
			//
			buttons = new ImageView[buttonNum];
			for (int i = 0; i < buttons.length; i++) {
				buttons[i] = new ImageView(getContext());
				buttons[i].setId(leftIds[i]);
				buttons[i].setImageResource(leftdrawRes[i]);
				buttons[i].setPadding(0, 5, 0, 5);
				buttons[i].setOnClickListener(this);
				LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(getViewWidth() * 120 / 144, getViewWidth() * 120 / 144);
				lp.setMargins(margin, 0, margin, 0);
				popLayout.addView(buttons[i], lp);
			}
			//
			imageRight = new ImageView(getContext());
			imageRight.setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_bg_r));
			imageRight.setScaleType(ScaleType.FIT_XY);
			LinearLayout.LayoutParams imageRightParams = new LinearLayout.LayoutParams(getViewWidth() * 68 / 144, getViewWidth() * 120 / 144);
			imageRightParams.setMargins(0, topMargin, 0, topMargin);
			allLayout.addView(imageRight, imageRightParams);
			//
			popWidth = (120 * buttonNum + 68) * getViewWidth() / 144 + margin * buttonNum * 2;

			mPopWin = new PopupWindow(allLayout, popWidth, WindowManager.LayoutParams.WRAP_CONTENT);
			mPopWin.setAnimationStyle(android.R.style.Animation);
			mPopWin.setFocusable(false);
			mPopWin.setTouchable(true);
			mPopWin.setOutsideTouchable(true);
			mPopWin.setOnDismissListener(new OnDismissListener() {

				@Override
				public void onDismiss() {
					setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_image2));
					handler.postDelayed(runnable, 5000);
				}
			});
		}

		if (wLayoutParams.x == 0) {
			setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_image2l));
			for (int i = 0; i < buttons.length; i++) {
				buttons[i].setId(leftIds[i]);
				buttons[i].setImageResource(leftdrawRes[i]);
			}
			imageLeft.setVisibility(View.GONE);
			imageRight.setVisibility(View.VISIBLE);
			// mPopWin.showAtLocation(this, Gravity.LEFT | Gravity.TOP, getViewWidth() * 110 / 144, 0);
			mPopWin.showAtLocation(this, Gravity.LEFT | Gravity.TOP, getViewWidth(), 0);
		} else {
			setImageResource(ResUtil.getDrawableId(Resource.drawable.snailbilling_float_image2r));
			for (int i = 0; i < buttons.length; i++) {
				buttons[i].setId(rightIds[i]);
				buttons[i].setImageResource(rightdrawRes[i]);
			}
			imageLeft.setVisibility(View.VISIBLE);
			imageRight.setVisibility(View.GONE);
			// mPopWin.showAtLocation(this, Gravity.LEFT | Gravity.TOP, -popWidth + getViewWidth() * 34 / 144, 0);
			mPopWin.showAtLocation(this, Gravity.LEFT | Gravity.TOP, -popWidth + 1, 0);
		}
	}

	public static int dpToPx(float dp, Context context) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
	}

	interface FloatId {
		int FLOAT_IMAGE = 0x6f000001;
		int FLOAT_ICON1 = 0x6f000002;
		int FLOAT_ICON2 = 0x6f000003;
		int FLOAT_ICON3 = 0x6f000004;
	}

	@Override
	public void onHide() {
		setVisibility(getVisibility());
	}

	// public static interface HideEvent{
	// public void onHide();
	// }

}

interface HideEvent {
	public void onHide();
}
